/**
 * 
 */
package com.rpg.osric.player;

import com.dalonedrau.jogl.engine.GameApplet;
import com.dalonedrau.jogl.engine.Interactive;
import com.dalonedrau.pool.PooledStringBuilder;
import com.dalonedrau.pool.StringBuilderPool;
import com.rpg.base.Player;
import com.rpg.osric.globals.OsricConsts;
import com.rpg.osric.globals.OsricEquipmentConsts;
import com.rpg.osric.globals.OsricIOConsts;
import com.rpg.osric.globals.OsricPlayerConsts;
import com.rpg.osric.item.OsricInteractiveObject;

/**
 * Completed:<br>
 * - Adjusting statistics by race<br>
 * - Adjusting secondary statistics by race<br>
 * - awarding experience points<br>
 * - determining experience points required for gaining a level<br>
 * - setting the base saving throw by class<br>
 * - setting base THAC0 by class<br>
 * To Be Done:<br>
 * - finalizing base character ability scores by race
 * @author Donald
 */
public class OsricPlayer implements Player<OsricCharacter> {
	/** the singleton instance of {@link OsricPlayer}. */
	private static OsricPlayer	instance;
	/**
	 * Gets the singleton instance of {@link OsricPlayer}.
	 * @return {@link OsricPlayer}
	 */
	public static OsricPlayer getInstance() {
		if (OsricPlayer.instance == null) {
			OsricPlayer.instance = new OsricPlayer();
		}
		return OsricPlayer.instance;
	}
	/** Hidden constructor. */
	private OsricPlayer() {}
	/**
	 * Adjusts the values for all secondary statistics based on their full
	 * attribute values.
	 * @param pc the {@link OsricCharacter}
	 * @throws Exception if an error occurs
	 */
	private void adj2ndaryStatsByAttribute(final OsricCharacter pc)
			throws Exception {
		adj2ndStatsStrength(pc);
		adj2ndStatsDexterity(pc);
		adj2ndStatsConstitution(pc);
		adj2ndStatsIntelligence(pc);
		adj2ndStatsWisdom(pc);
		adj2ndStatsCharisma(pc);
	}
	/**
	 * Adjusts the values for all secondary statistics based on their race.
	 * @param pc the {@link OsricCharacter}
	 */
	private void adj2ndaryStatsByRace(final OsricCharacter pc)
			throws Exception {
		switch (pc.getRace()) {
		case OsricPlayerConsts.RACE_DWARF:
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 2);
			pc.adjustRacialAttackBonus(OsricPlayerConsts.RACE_GOBLIN, 1);
			pc.adjustRacialAttackBonus(OsricPlayerConsts.RACE_HALFORC, 1);
			pc.adjustRacialAttackBonus(OsricPlayerConsts.RACE_HOBGOBLIN, 1);
			pc.adjustRacialAttackBonus(OsricPlayerConsts.RACE_ORC, 1);

			int pb =
					(int) ((pc
							.getBaseAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION)
						+ pc.getModAbilityScore(
								OsricPlayerConsts.ABILITY_CONSTITUTION))
					/ 3.5f);
			pc.adjustSavingThrowModifier(OsricPlayerConsts.SAVE_VS_SPELLS, pb);
			pc.adjustSavingThrowModifier(OsricPlayerConsts.SAVE_VS_POISION, pb);
			break;
		case OsricPlayerConsts.RACE_ELF:
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES,
					Math.max(
							0,
							(int) pc.getFullAbilityScore(
									OsricPlayerConsts.ABILITY_INTELLIGENCE) - 15));
			pc.adjustResistance(OsricPlayerConsts.RESISTANCE_TYPE_CHARM, 0.9f);
			pc.adjustResistance(OsricPlayerConsts.RESISTANCE_TYPE_SLEEP, 0.9f);
			pc.adjustWeaponBonus(OsricEquipmentConsts.WEAPON_TYPE_BOW, 1);
			pc.adjustWeaponBonus(OsricEquipmentConsts.WEAPON_TYPE_SWORD_LONG, 1);
			pc.adjustWeaponBonus(OsricEquipmentConsts.WEAPON_TYPE_SWORD_SHORT,
					1);
			break;
		case OsricPlayerConsts.RACE_GNOME:
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 2);
			pc.adjustRacialAttackBonus(OsricPlayerConsts.RACE_GOBLIN, 1);
			pc.adjustRacialAttackBonus(OsricPlayerConsts.RACE_KOBOLD, 1);
			pb =
					(int) ((pc
							.getBaseAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION)
						+ pc.getModAbilityScore(
								OsricPlayerConsts.ABILITY_CONSTITUTION))
					/ 3.5f);
			pc.adjustSavingThrowModifier(OsricPlayerConsts.SAVE_VS_SPELLS, pb);
			pc.adjustSavingThrowModifier(OsricPlayerConsts.SAVE_VS_POISION, pb);
			break;
		case OsricPlayerConsts.RACE_HALFELF:
			pc.adjustResistance(
					OsricPlayerConsts.RESISTANCE_TYPE_CHARM, 0.3f);
			pc.adjustResistance(
					OsricPlayerConsts.RESISTANCE_TYPE_SLEEP, 0.3f);
			break;
		case OsricPlayerConsts.RACE_HALFLING:
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES,
					Math.max(0, (int) pc.getFullAbilityScore(
							OsricPlayerConsts.ABILITY_INTELLIGENCE) - 16));
			pb =
					(int) ((pc
							.getBaseAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION)
						+ pc.getModAbilityScore(
								OsricPlayerConsts.ABILITY_CONSTITUTION))
					/ 3.5f);
			pc.adjustSavingThrowModifier(OsricPlayerConsts.SAVE_VS_SPELLS, pb);
			pc.adjustSavingThrowModifier(OsricPlayerConsts.SAVE_VS_POISION, pb);
			pc.adjustWeaponBonus(OsricEquipmentConsts.WEAPON_TYPE_BOW, 3);
			pc.adjustWeaponBonus(OsricEquipmentConsts.WEAPON_TYPE_SLING, 3);
			break;
		case OsricPlayerConsts.RACE_HALFORC:
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 2);
			break;
		default:
			break;
		}
	}
	/**
	 * Adjusts all secondary statistics related to the Charisma ability score.
	 * @param pc the {@link OsricCharacter}
	 */
	private void adj2ndStatsCharisma(final OsricCharacter pc) throws Exception {
		float cha = pc.getFullAbilityScore(OsricPlayerConsts.ABILITY_CHARISMA);
		if (cha <= 3f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					-30);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					-25);
		} else if (cha == 4f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					-25);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					-20);
		} else if (cha == 5f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					-20);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					-15);
		} else if (cha == 6f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					-15);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					-10);
		} else if (cha == 7f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					-10);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					-5);
		} else if (cha == 8f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					-5);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT, 0);
		} else if (cha >= 9f && cha <= 11f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 4);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT, 0);
		} else if (cha == 12f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 5);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT, 0);
		} else if (cha == 13f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 5);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT, 5);
		} else if (cha == 14f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 6);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					5);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					10);
		} else if (cha == 15f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 7);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					15);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					15);
		} else if (cha == 16f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 8);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					20);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					25);
		} else if (cha == 17f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 10);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					30);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					30);
		} else if (cha == 18f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 15);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					40);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					35);
		} else if (cha == 19f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_HENCHMEN, 20);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HENCHMEN_LOYALTY_ADJUSTMENT,
					50);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_REACTION_ADJUSTMENT,
					40);
		}
	}
	/**
	 * Adjusts all secondary statistics related to the Constitution ability
	 * score.
	 * @param pc the {@link OsricCharacter}
	 */
	private void adj2ndStatsConstitution(final OsricCharacter pc)
			throws Exception {
		float con = pc
				.getFullAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION);
		if (con <= 3f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, -2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					40);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					35);
		} else if (con == 4f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, -1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					45);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					40);
		} else if (con == 5f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, -1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					50);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					45);
		} else if (con == 6f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, -1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					55);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					50);
		} else if (con == 7f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					60);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					55);
		} else if (con == 8f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					65);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					60);
		} else if (con == 9f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					70);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					65);
		} else if (con == 10f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					75);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					70);
		} else if (con == 11f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					80);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					75);
		} else if (con == 12f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					85);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					80);
		} else if (con == 13f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					90);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					85);
		} else if (con == 14f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					92);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					88);
		} else if (con == 15f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					94);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					91);
		} else if (con == 16f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					96);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					95);
		} else if (con == 17f) {
			int prof = pc.getProfession();
			if (prof == OsricPlayerConsts.CLASS_FIGHTER
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER_MAGE
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_RANGER
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_ASSASSIN
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_ILLUSIONIST
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE_THIEF
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_THIEF
					|| prof == OsricPlayerConsts.CLASS_PALADIN
					|| prof == OsricPlayerConsts.CLASS_RANGER) {
				pc.adjustSecondaryModifier(
						OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 3);
			} else {
				pc.adjustSecondaryModifier(
						OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 2);
			}
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					98);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					97);
		} else if (con == 18f) {
			int prof = pc.getProfession();
			if (prof == OsricPlayerConsts.CLASS_FIGHTER
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER_MAGE
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_RANGER
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_ASSASSIN
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_ILLUSIONIST
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE_THIEF
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_THIEF
					|| prof == OsricPlayerConsts.CLASS_PALADIN
					|| prof == OsricPlayerConsts.CLASS_RANGER) {
				pc.adjustSecondaryModifier(
						OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 4);
			} else {
				pc.adjustSecondaryModifier(
						OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 2);
			}
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					100);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					99);
		} else if (con == 19f) {
			int prof = pc.getProfession();
			if (prof == OsricPlayerConsts.CLASS_FIGHTER
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER_MAGE
					|| prof == OsricPlayerConsts.CLASS_MULTI_CLERIC_RANGER
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_ASSASSIN
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_ILLUSIONIST
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE_THIEF
					|| prof == OsricPlayerConsts.CLASS_MULTI_FIGHTER_THIEF
					|| prof == OsricPlayerConsts.CLASS_PALADIN
					|| prof == OsricPlayerConsts.CLASS_RANGER) {
				pc.adjustSecondaryModifier(
						OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 5);
			} else {
				pc.adjustSecondaryModifier(
						OsricPlayerConsts.SECONDARY_MODIFIER_HP_ADJUSTMENT, 2);
			}
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_RESURRECTION_ADJUSTMENT,
					100);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURVIVE_SYSTEM_SHOCK_ADJUSTMENT,
					99);
		}
	}
	/**
	 * Adjusts all secondary statistics related to the Dexterity ability score.
	 * @param pc the {@link OsricCharacter}
	 */
	private void adj2ndStatsDexterity(final OsricCharacter pc) throws Exception {
		float dex = pc.getFullAbilityScore(OsricPlayerConsts.ABILITY_DEXTERITY);
		if (dex <= 3f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT,
					-3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					-3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, 4);
		} else if (dex == 4f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT,
					-2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					-2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, 3);
		} else if (dex == 5f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT,
					-1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					-1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, 2);
		} else if (dex == 6f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, 1);
		} else if (dex >= 7f && dex <= 14f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, 0);
		} else if (dex == 15f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, -1);
		} else if (dex == 16f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, -2);
		} else if (dex == 17f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT, 2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, -3);
		} else if (dex >= 18f && dex <= 19f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_SURPRISE_ADJUSTMENT, 3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MISSILE_THAC0_ADJUSTMENT,
					3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_AC_ADJUSTMENT, -4);
		}
	}
	/**
	 * Adjusts all secondary statistics related to the Intelligence ability
	 * score.
	 * @param pc the {@link OsricCharacter}
	 */
	private void adj2ndStatsIntelligence(final OsricCharacter pc)
			throws Exception {
		float inT = pc
				.getFullAbilityScore(OsricPlayerConsts.ABILITY_INTELLIGENCE);
		if (inT <= 7f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 0);
		} else if (inT >= 8f && inT <= 9f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 1);
		} else if (inT >= 10f && inT <= 11f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 2);
		} else if (inT >= 12f && inT <= 13f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 3);
		} else if (inT >= 14f && inT <= 15f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 4);
		} else if (inT == 16f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 5);
		} else if (inT == 17f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 6);
		} else if (inT == 18f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 7);
		} else if (inT == 19f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MAX_ADDL_LANGUAGES, 8);
		}
	}
	/**
	 * Adjusts all secondary statistics related to the Strength ability score.
	 * @param pc the {@link OsricCharacter}
	 */
	private void adj2ndStatsStrength(final OsricCharacter pc) throws Exception {
		float str = pc.getFullAbilityScore(OsricPlayerConsts.ABILITY_STRENGTH);
		if (str <= 3f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, -3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, -1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					-35);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.16667f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 0);
		} else if (str >= 4f && str <= 5f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, -2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, -1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					-25);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.16667f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 0);
		} else if (str >= 6f && str <= 7f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, -1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					-15);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.16667f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 0);
		} else if (str >= 8 && str <= 9) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					0);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.33333f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 1);
		} else if (str >= 10f && str <= 11f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					0);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.33333f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 2);
		} else if (str >= 12 && str <= 13) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					10);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.33333f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 4);
		} else if (str >= 14f && str <= 15f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					20);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.33333f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 7);
		} else if (str == 16f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 0);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					35);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.5f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 10);
		} else if (str == 17f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					50);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.5f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 13);
		} else if (str == 18f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					75);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.5f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 16);
		} else if (str >= 18.01f && str <= 18.50f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 1);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					100);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.5f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 20);
		} else if (str >= 18.51f && str <= 18.75f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					125);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.66667f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 25);
		} else if (str >= 18.76f && str <= 18.90f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 4);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					150);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.66667f);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 30);
		} else if (str >= 18.91f && str <= 18.99f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 2);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 5);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					200);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.66667f);
			pc.adjustForceDoorChance(
					OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0.16667f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 35);
		} else if (str == 19f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_THAC0_ADJUSTMENT, 3);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_DMG_ADJUSTMENT, 6);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_ENCUMBRANCE_ADJUSTMENT,
					300);
			pc.adjustForceDoorChance(OsricConsts.DOOR_TYPE_LOCKED, 0.83333f);
			pc.adjustForceDoorChance(
					OsricConsts.DOOR_TYPE_MAGICALLY_LOCKED, 0.16667f);
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_BEND_BARS, 40);
		}
	}
	/**
	 * Adjusts all secondary statistics related to the Wisdom ability score.
	 * @param pc the {@link OsricCharacter}
	 */
	private void adj2ndStatsWisdom(final OsricCharacter pc) throws Exception {
		float wis = pc.getFullAbilityScore(OsricPlayerConsts.ABILITY_WISDOM);
		if (wis <= 3f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					-3);
		} else if (wis == 4f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					-2);
		} else if (wis >= 5f && wis <= 7f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					-1);
		} else if (wis >= 8f && wis <= 14f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					0);
		} else if (wis == 15f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					1);
		} else if (wis == 16f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					2);
		} else if (wis == 17f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					3);
		} else if (wis == 18f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					4);
		} else if (wis == 19f) {
			pc.adjustSecondaryModifier(
					OsricPlayerConsts.SECONDARY_MODIFIER_MENTAL_SAVE_ADJUSTMENT,
					5);
		}
	}
	/**
	 * Assigns the player's race.
	 * @param pc the {@link OsricCharacter}
	 * @param race the race
	 */
	public void assignRaceDuringCharacterCreation(final OsricCharacter pc,
			final int race) throws Exception {
		pc.setRace(race);
		pc.clearModAbilityScores();
		clear2ndaryStats(pc);
		pc.clearRacialLanguages();
		pc.setRacialLanguage(OsricConsts.LANGUAGE_COMMON);
		pc.clearLearnedLanguages();
		pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_INFRAVISION, 0);
		setRacialAbilityModifiers(pc);
		switch (race) {
		case OsricPlayerConsts.RACE_DWARF:
			pc.setRacialLanguage(OsricConsts.LANGUAGE_DWARFISH);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GNOMISH);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GOBLIN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_KOBOLD);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_ORCISH);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_INFRAVISION, 60);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_MOVEMENT_RATE, 90);
			break;
		case OsricPlayerConsts.RACE_ELF:
			pc.setRacialLanguage(OsricConsts.LANGUAGE_ELVEN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GNOLL);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GNOMISH);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GOBLIN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_HALFLING);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_HOBGOBLIN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_ORCISH);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_INFRAVISION, 60);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_MOVEMENT_RATE, 120);
			break;
		case OsricPlayerConsts.RACE_GNOME:
			pc.setRacialLanguage(OsricConsts.LANGUAGE_DWARFISH);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GNOMISH);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GOBLIN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_HALFLING);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_KOBOLD);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_SPECIAL_BURROWING_ANIMAL);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_INFRAVISION, 60);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_MOVEMENT_RATE, 90);
			break;
		case OsricPlayerConsts.RACE_HALFELF:
			pc.setRacialLanguage(OsricConsts.LANGUAGE_ELVEN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GNOLL);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GNOMISH);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GOBLIN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_HALFLING);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_HOBGOBLIN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_ORCISH);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_INFRAVISION, 60);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_MOVEMENT_RATE, 120);
			break;
		case OsricPlayerConsts.RACE_HALFLING:
			pc.setRacialLanguage(OsricConsts.LANGUAGE_DWARFISH);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GNOMISH);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_GOBLIN);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_HALFLING);
			pc.setRacialLanguage(OsricConsts.LANGUAGE_ORCISH);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_INFRAVISION, 60);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_MOVEMENT_RATE, 90);
			break;
		case OsricPlayerConsts.RACE_HALFORC:
			pc.setRacialLanguage(OsricConsts.LANGUAGE_ORCISH);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_INFRAVISION, 60);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_MOVEMENT_RATE, 120);
			break;
		default: // HUMAN
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_MOVEMENT_RATE, 120);
			break;
		}
		pc.setAllFullAbilityScores();
		adj2ndaryStatsByAttribute(pc);
		adj2ndaryStatsByRace(pc);
	}
	/**
	 * Clears the values for all secondary statistics, such as bonus to hit, AC,
	 * etc..
	 * @param pc the {@link OsricCharacter}
	 */
	private void clear2ndaryStats(final OsricCharacter pc) {
		pc.clearSecondaryModifiers();
		pc.clearForceDoorChances();
		pc.clearRacialAttackBonuses();
		pc.clearResistances();
		pc.clearSavingThrowModifiers();
		pc.clearWeaponBonuses();
	}
	public void finalizeCharacterCreation(final OsricCharacter pc)
			throws Exception {
		// Adjust base scores for race
		switch (pc.getRace()) {
		case OsricPlayerConsts.RACE_DWARF:
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_CONSTITUTION) + 1);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_CHARISMA,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_CHARISMA) - 1);
			break;
		case OsricPlayerConsts.RACE_ELF:
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_DEXTERITY,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_DEXTERITY) + 1);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_CONSTITUTION) - 1);
			break;
		case OsricPlayerConsts.RACE_GNOME:
		case OsricPlayerConsts.RACE_HALFELF:
			break;
		case OsricPlayerConsts.RACE_HALFLING:
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_STRENGTH,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_STRENGTH) - 1);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_DEXTERITY,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_DEXTERITY) + 1);
			break;
		case OsricPlayerConsts.RACE_HALFORC:
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_STRENGTH,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_STRENGTH) + 1);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_CONSTITUTION) + 1);
			pc.setBaseAbilityScore(OsricPlayerConsts.ABILITY_CHARISMA,
					pc.getBaseAbilityScore(
							OsricPlayerConsts.ABILITY_CHARISMA) - 2);
			break;
		default:
			break;
		}
	}
	public float getBaseToHitRoll(final OsricCharacter pc, final int target)
			throws Exception {
		float roll = 0;
		int level = pc.getLevel();
		if (pc.hasIOFlag(OsricIOConsts.IO_MULTI_CLASS)) {
			// pc.getLevelForMulti(profession)
		}
		OsricInteractiveObject io =
				(OsricInteractiveObject) Interactive.getInstance()
						.getIO(target);
		// striking an NPC
		if (io.hasIOFlag(OsricIOConsts.IO_NPC)) {
			float targAc = io.getNPCData().getArmorClass();
			switch (pc.getProfession()) {
			case OsricPlayerConsts.CLASS_ASSASSIN:
			case OsricPlayerConsts.CLASS_THIEF:
				roll = OsricProfessionUtil.getInstance().getBaseToHitThief(
						level, targAc);
				break;
			case OsricPlayerConsts.CLASS_CLERIC:
			case OsricPlayerConsts.CLASS_DRUID:
				roll = OsricProfessionUtil.getInstance().getBaseToHitCleric(
						level, targAc);
				break;
			case OsricPlayerConsts.CLASS_FIGHTER:
			case OsricPlayerConsts.CLASS_PALADIN:
			case OsricPlayerConsts.CLASS_RANGER:
				roll = OsricProfessionUtil.getInstance().getBaseToHitFighter(
						level, targAc);
				break;
			case OsricPlayerConsts.CLASS_ILLUSIONIST:
			case OsricPlayerConsts.CLASS_MAGE:
				roll = OsricProfessionUtil.getInstance().getBaseToHitMage(
						level, targAc);
				break;
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_ASSASSIN:
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_MAGE:
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_THIEF:
				roll = OsricProfessionUtil.getInstance().getBaseToHitCleric(
						pc.getLevelForMulti(OsricPlayerConsts.CLASS_CLERIC),
						targAc);
				break;
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER:
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER_MAGE:
			case OsricPlayerConsts.CLASS_MULTI_FIGHTER_ASSASSIN:
			case OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE:
			case OsricPlayerConsts.CLASS_MULTI_FIGHTER_THIEF:
				roll = OsricProfessionUtil.getInstance().getBaseToHitFighter(
						pc.getLevelForMulti(OsricPlayerConsts.CLASS_FIGHTER),
						targAc);
				break;
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_RANGER:
				roll = OsricProfessionUtil.getInstance().getBaseToHitFighter(
						pc.getLevelForMulti(OsricPlayerConsts.CLASS_RANGER),
						targAc);
				break;
			case OsricPlayerConsts.CLASS_MULTI_ILLUSIONIST_THIEF:
			case OsricPlayerConsts.CLASS_MULTI_MAGE_THIEF:
				roll = OsricProfessionUtil.getInstance().getBaseToHitThief(
						pc.getLevelForMulti(OsricPlayerConsts.CLASS_THIEF),
						targAc);
				break;
			}
		}
		return roll;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public long getXPforLevel(final int profession, final int level) {
		long required = 0;
		switch (profession) {
		case OsricPlayerConsts.CLASS_ASSASSIN:
			switch (level) {
			case 15:
				required += 500000;
			case 14:
				required += 250000;
			case 13:
				required += 150000;
			case 12:
				required += 200000;
			case 11:
				required += 100000;
			case 10:
				required += 99500;
			case 9:
				required += 101500;
			case 8:
				required += 49000;
			case 7:
				required += 25250;
			case 6:
				required += 12500;
			case 5:
				required += 6500;
			case 4:
				required += 2750;
			case 3:
				required += 1400;
			case 2:
				required += 1600;
			}
			break;
		case OsricPlayerConsts.CLASS_CLERIC:
			if (level == 2) {
				required = 1550;
			} else if (level == 3) {
				required = 2900;
			} else if (level == 4) {
				required = 6000;
			} else if (level == 5) {
				required = 13250;
			} else if (level == 6) {
				required = 27000;
			} else if (level == 7) {
				required = 55000;
			} else if (level == 8) {
				required = 110000;
			} else if (level == 9) {
				required = 220000;
			} else if (level >= 10) {
				required = 450000 + 225000 * level - 10;
			}
			break;
		case OsricPlayerConsts.CLASS_DRUID:
			switch (level) {
			case 14:
				required += 750000;
			case 13:
				required += 450000;
			case 12:
				required += 100000;
			case 11:
				required += 75000;
			case 10:
				required += 35000;
			case 9:
				required += 30000;
			case 8:
				required += 25000;
			case 7:
				required += 15000;
			case 6:
				required += 8000;
			case 5:
				required += 4000;
			case 4:
				required += 4000;
			case 3:
				required += 2000;
			case 2:
				required += 2000;
			}
			break;
		case OsricPlayerConsts.CLASS_FIGHTER:
			if (level == 2) {
				required = 1900;
			} else if (level == 3) {
				required = 4250;
			} else if (level == 4) {
				required = 7750;
			} else if (level == 5) {
				required = 16000;
			} else if (level == 6) {
				required = 35000;
			} else if (level == 7) {
				required = 75000;
			} else if (level == 8) {
				required = 125000;
			} else if (level >= 9) {
				required = 250000 + 250000 * level - 9;
			}
			break;
		case OsricPlayerConsts.CLASS_ILLUSIONIST:
			if (level == 2) {
				required = 2500;
			} else if (level == 3) {
				required = 4750;
			} else if (level == 4) {
				required = 9000;
			} else if (level == 5) {
				required = 18000;
			} else if (level == 6) {
				required = 35000;
			} else if (level == 7) {
				required = 60250;
			} else if (level == 8) {
				required = 95000;
			} else if (level == 9) {
				required = 144500;
			} else if (level >= 10) {
				required = 220000 + 220000 * level - 10;
			}
			break;
		case OsricPlayerConsts.CLASS_MAGE:
			if (level == 2) {
				required = 2400;
			} else if (level == 3) {
				required = 4800;
			} else if (level == 4) {
				required = 10250;
			} else if (level == 5) {
				required = 22000;
			} else if (level == 6) {
				required = 40000;
			} else if (level == 7) {
				required = 60000;
			} else if (level == 8) {
				required = 80000;
			} else if (level == 9) {
				required = 140000;
			} else if (level == 10) {
				required = 250000;
			} else if (level >= 11) {
				required = 375000 + 375000 * level - 11;
			}
			break;
		case OsricPlayerConsts.CLASS_PALADIN:
			if (level == 2) {
				required = 2550;
			} else if (level == 3) {
				required = 5500;
			} else if (level == 4) {
				required = 12500;
			} else if (level == 5) {
				required = 25000;
			} else if (level == 6) {
				required = 45000;
			} else if (level == 7) {
				required = 95000;
			} else if (level == 8) {
				required = 175000;
			} else if (level == 9) {
				required = 325000;
			} else if (level == 10) {
				required = 600000;
			} else if (level >= 11) {
				required = 1000000 + 350000 * level - 11;
			}
			break;
		case OsricPlayerConsts.CLASS_RANGER:
			if (level == 2) {
				required = 2250;
			} else if (level == 3) {
				required = 4500;
			} else if (level == 4) {
				required = 9500;
			} else if (level == 5) {
				required = 20000;
			} else if (level == 6) {
				required = 40000;
			} else if (level == 7) {
				required = 90000;
			} else if (level == 8) {
				required = 150000;
			} else if (level == 9) {
				required = 225000;
			} else if (level >= 10) {
				required = 325000 + 220000 * level - 10;
			}
			break;
		case OsricPlayerConsts.CLASS_THIEF:
			if (level == 2) {
				required = 1250;
			} else if (level == 3) {
				required = 2500;
			} else if (level == 4) {
				required = 5000;
			} else if (level == 5) {
				required = 10000;
			} else if (level == 6) {
				required = 20000;
			} else if (level == 7) {
				required = 40000;
			} else if (level == 8) {
				required = 70000;
			} else if (level == 9) {
				required = 110000;
			} else if (level == 10) {
				required = 160000;
			} else if (level >= 11) {
				required = 220000 + 220000 * level - 11;
			}
			break;
		}
		return required;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void modifyXP(final OsricCharacter pc, final long val) {
		pc.adjustXp(val);
		int nextLevel = pc.getLevel() + 1;
		// check if player is eligible for next level
		if (pc.hasIOFlag(OsricIOConsts.IO_MULTI_CLASS)) {
			try {
				float realXp = pc.getXp() / 2f;
				switch (pc.getProfession()) {
				case OsricPlayerConsts.CLASS_MULTI_CLERIC_ASSASSIN:
					int l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_CLERIC);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_CLERIC,
							l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_ASSASSIN);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_ASSASSIN, l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_CLERIC);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_CLERIC,
							l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_FIGHTER);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_FIGHTER, l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER_MAGE:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_CLERIC);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_CLERIC,
							l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_FIGHTER);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_FIGHTER, l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_MAGE);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_MAGE, l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_CLERIC_MAGE:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_CLERIC);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_CLERIC,
							l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_MAGE);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_MAGE, l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_CLERIC_RANGER:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_CLERIC);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_CLERIC,
							l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_RANGER);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_RANGER,
							l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_CLERIC_THIEF:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_CLERIC);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_CLERIC,
							l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_THIEF);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_THIEF,
							l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_FIGHTER_ASSASSIN:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_CLERIC);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_CLERIC,
							l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_ASSASSIN);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_ASSASSIN, l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_FIGHTER_ILLUSIONIST:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_FIGHTER);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_FIGHTER, l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_ILLUSIONIST);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_ILLUSIONIST, l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_FIGHTER);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_FIGHTER, l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_MAGE);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_MAGE, l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE_THIEF:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_FIGHTER);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_FIGHTER, l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_MAGE);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_MAGE, l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_THIEF);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_THIEF,
							l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_FIGHTER_THIEF:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_FIGHTER);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_FIGHTER, l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_THIEF);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_THIEF,
							l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_ILLUSIONIST_THIEF:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_ILLUSIONIST);
					if (realXp >= getXPforLevel(
							OsricPlayerConsts.CLASS_ILLUSIONIST, l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_THIEF);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_THIEF,
							l)) {
						levelUp(pc);
					}
					break;
				case OsricPlayerConsts.CLASS_MULTI_MAGE_THIEF:
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_MAGE);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_MAGE, l)) {
						levelUp(pc);
					}
					l = pc.getLevelForMulti(OsricPlayerConsts.CLASS_THIEF);
					if (realXp >= getXPforLevel(OsricPlayerConsts.CLASS_THIEF,
							l)) {
						levelUp(pc);
					}
					break;
				}
			} catch (Exception ex) {
				JOGLErrorHandler.getInstance().fatalError(ex);
			}
		} else {
			if (pc.getXp() >= getXPforLevel(pc.getProfession(), nextLevel)) {
				levelUp(pc);
			}
		}
		/*
		 * original implementation is to call level up for each level the pc has
		 * gained. it's possible to gain more than one level with a single
		 * experience award for (long i = 1; i < 11; i++) { long lvup = 0; if (i
		 * > player.level) { if (player.xp >= GetXPforLevel(i)) { lvup = 1; } if
		 * (lvup) { ARX_PLAYER_LEVEL_UP(); } } }
		 */
	}
	/**
	 * Sets the base saving throw for a character.
	 * @param pc the {@link OsricCharacter}
	 * @throws Exception if an error occurs
	 */
	private void setBaseSavingThrows(final OsricCharacter pc) throws Exception {
		for (int i = 0; i < OsricPlayerConsts.SAVE_VS_TOTAL; i++) {
			switch (pc.getProfession()) {
			case OsricPlayerConsts.CLASS_ASSASSIN:
			case OsricPlayerConsts.CLASS_THIEF:
				pc.setBaseSavingThrow(i,
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowThief(
										pc.getLevel(), i));
				break;
			case OsricPlayerConsts.CLASS_CLERIC:
			case OsricPlayerConsts.CLASS_DRUID:
				pc.setBaseSavingThrow(i,
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowCleric(
										pc.getLevel(), i));
				break;
			case OsricPlayerConsts.CLASS_FIGHTER:
				pc.setBaseSavingThrow(i,
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowFighter(
										pc.getLevel(), i));
				break;
			case OsricPlayerConsts.CLASS_ILLUSIONIST:
			case OsricPlayerConsts.CLASS_MAGE:
				pc.setBaseSavingThrow(i,
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowMage(
										pc.getLevel(), i));
				break;
			case OsricPlayerConsts.CLASS_PALADIN:
				pc.setBaseSavingThrow(i,
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowPaladin(
										pc.getLevel(), i));
				break;
			case OsricPlayerConsts.CLASS_RANGER:
				pc.setBaseSavingThrow(i,
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowRanger(
										pc.getLevel(), i));
				break;
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_ASSASSIN:
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_THIEF:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowCleric(pc.getLevel(), i),
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowThief(pc.getLevel(), i)));
				break;
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowCleric(pc.getLevel(), i),
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowFighter(pc.getLevel(), i)));
				break;
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_FIGHTER_MAGE:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowCleric(pc.getLevel(), i),
						Math.min(
								OsricProfessionUtil.getInstance()
										.getBaseSavingThrowFighter(
												pc.getLevel(), i),
								OsricProfessionUtil.getInstance()
										.getBaseSavingThrowMage(pc.getLevel(),
												i))));
				break;
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_MAGE:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowCleric(pc.getLevel(), i),
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowMage(pc.getLevel(), i)));
				break;
			case OsricPlayerConsts.CLASS_MULTI_CLERIC_RANGER:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowCleric(pc.getLevel(), i),
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowRanger(pc.getLevel(), i)));
				break;
			case OsricPlayerConsts.CLASS_MULTI_FIGHTER_ASSASSIN:
			case OsricPlayerConsts.CLASS_MULTI_FIGHTER_THIEF:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowFighter(pc.getLevel(), i),
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowThief(pc.getLevel(), i)));
				break;
			case OsricPlayerConsts.CLASS_MULTI_FIGHTER_ILLUSIONIST:
			case OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowFighter(pc.getLevel(), i),
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowMage(pc.getLevel(), i)));
				break;
			case OsricPlayerConsts.CLASS_MULTI_FIGHTER_MAGE_THIEF:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowFighter(pc.getLevel(), i),
						Math.min(
								OsricProfessionUtil.getInstance()
										.getBaseSavingThrowMage(pc.getLevel(),
												i),
								OsricProfessionUtil.getInstance()
										.getBaseSavingThrowThief(pc.getLevel(),
												i))));
				break;
			case OsricPlayerConsts.CLASS_MULTI_ILLUSIONIST_THIEF:
			case OsricPlayerConsts.CLASS_MULTI_MAGE_THIEF:
				pc.setBaseSavingThrow(i, Math.min(
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowMage(pc.getLevel(), i),
						OsricProfessionUtil.getInstance()
								.getBaseSavingThrowThief(pc.getLevel(), i)));
				break;
			default:
				PooledStringBuilder sb = StringBuilderPool.getInstance()
						.getStringBuilder();
				sb.append("Error! No saving throws defined for profession ");
				sb.append(pc.getProfession());
				Exception ex = new Exception(sb.toString());
				sb.returnToPool();
				throw ex;
			}
		}
	}
	/**
	 * Sets all ability modifiers affected by the player's race.
	 * @param pc the {@link OsricCharacter}
	 */
	private void setRacialAbilityModifiers(final OsricCharacter pc)
			throws Exception {
		switch (pc.getRace()) {
		case OsricPlayerConsts.RACE_DWARF:
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION, 1);
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_CHARISMA, -1);
			break;
		case OsricPlayerConsts.RACE_ELF:
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_DEXTERITY, 1);
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION, -1);
			break;
		case OsricPlayerConsts.RACE_GNOME:
		case OsricPlayerConsts.RACE_HALFELF:
			break;
		case OsricPlayerConsts.RACE_HALFLING:
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_STRENGTH, -1);
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_DEXTERITY, 1);
			break;
		case OsricPlayerConsts.RACE_HALFORC:
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_STRENGTH, 1);
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_CONSTITUTION, 1);
			pc.adjModAbilityScore(OsricPlayerConsts.ABILITY_CHARISMA, -2);
			break;
		default:
			break;
		}
	}
}
